<template>
  <div class="code-panel-share">
    <el-select class="code-mode-select" v-model="mode" @change="onChangeMode">
      <el-option
        v-for="m in modes"
        :key="m.value"
        :label="m.label"
        :value="m.value"
      >
      </el-option>
    </el-select>
    <div style="border-radius: 4px; border: solid 1px #d7dae2; padding: 4px">
      <textarea id="destory_tag" ref="editer"></textarea>
    </div>
  </div>
</template>

<script>
// 引入全局实例
import CodeMirror from "codemirror/lib/codemirror";
// 核心样式
import "codemirror/lib/codemirror.css";
// 引入主题后还需要在 options 中指定主题才会生效
import "codemirror/theme/neat.css";
// 代码折叠
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/xml-fold.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/comment-fold.js";
// 括号标签匹配
import "codemirror/addon/edit/closebrackets.js";
import "codemirror/addon/edit/closetag.js";
// 代码提示
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/javascript-hint.js";
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
import "codemirror/mode/htmlmixed/htmlmixed.js";
import "codemirror/mode/css/css.js";
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/xml/xml.js";
import "codemirror/mode/markdown/markdown.js";
import "codemirror/mode/python/python.js";
import "codemirror/mode/vue/vue.js";

//协同编辑必要组件
import sharedb from "sharedb/lib/client";
import otText from "ot-text";
import ShareDBCodeMirror from "@/plugins/sharedb-codemirror";

export default {
  name: "CodePanelShare",
  props: {
    // 外部传入的内容，用于实现双向绑定
    value: {
      type: String,
      default: null,
    },
    // 外部传入的语法类型
    language: {
      type: String,
      default: null,
    },
    // doc: {
    //   type: String,
    //   default: null,
    // },
    // author: {
    //   type: String,
    //   default: null,
    // },
  },
  mounted() {
    // console.log("codePanelShare mounted");
    // 初始化编辑器
    this.initEditer();
    // this.initShareEdit("DEFAULT_DOC", "DEFAULT_AUTHOR");
  },
  methods: {
    // 初始化编辑器
    initEditer() {
      // 初始化编辑器实例，传入需要被实例化的文本域对象和默认配置
      this.editer = CodeMirror.fromTextArea(
        this.$refs["editer"],
        this.editerOptions
      );
      // 修改编辑器的语法配置
      this.editer.setOption("mode", `text/${this.mode}`);
      // 代码折叠
      this.editer.foldCode(CodeMirror.Pos(0, 0));
      // 编辑器赋值
      // this.editer.setValue(this.value || this.code);
      // // 动态绑定内容
      // this.editer.on("change", (editer) => {
      //   this.code = editer.getValue();
      //   // 允许父容器通过以下函数监听当前内容
      //   this.$emit("editerInput", this.code);
      // });
      // // 尝试从父容器获取语法类型
      // if (this.language) {
      //   // 获取具体的语法类型对象
      //   let modeObj = this.getMode(this.language);
      //   if (modeObj) {
      //     this.mode = modeObj.value;
      //     // 修改编辑器的语法配置
      //     this.editer.setOption("mode", `text/${this.mode}`);
      //     // 允许父容器通过以下函数监听当前的语法值
      //     this.$emit("modeChange", this.mode);
      //   }
      // }
    },
    //初始化协同编辑
    initShareEdit(doc, author) {
      if (this.shareDoc != "") {
        return;
      }
      // console.log("initShareEdit doc:", doc, "/author:", author);

      sharedb.types.map["json0"].registerSubtype(otText.type);
      this.socket = new WebSocket("ws://localhost:9001");
      this.shareConnection = new sharedb.Connection(this.socket);
      // 随机文档和作者
      // TODO: 一个doc对于一个题目的CodePanel 传入doc_name:roomid/problemid name:author
      // if (this.doc) {
      //   console.log("this.doc", this.doc);
      //   this.docName = this.doc;
      // } else {
      //   this.docName = "DEFAULT_DOC";
      // }
      // if (this.author) {
      //   console.log("this.author", this.author);
      //   this.authorName = this.author;
      // } else {
      //   this.authorName = "DEFAULT_AUTHOR";
      // }
      this.docName = doc;
      this.authorName = author;
      this.shareDoc = this.shareConnection.get(this.docName, this.authorName);
      // console.log("doc is: ", this.docName);
      // console.log("author is",this.authorName);
      ShareDBCodeMirror.attachDocToCodeMirror(this.shareDoc, this.editer, {
        key: "code",
        verbose: false,
      });
      this.socket.onopen = function(event) {
        console.log("WebSocket is open now.");
      };
      this.socket.onclose = () => {
        console.log("bye");
      };

      // websocket 提交事务（后端）
    },
    // 获取当前语法类型
    getMode(language) {
      // 在支持的语法类型列表中寻找传入的语法类型
      return this.modes.find((mode) => {
        // 所有的值都忽略大小写，方便比较
        let curLanguage = language.toLowerCase();
        let curLabel = mode.label.toLowerCase();
        let curValue = mode.value.toLowerCase();
        // 由于真实值可能不规范，例如 java 的真实值是 x-java ，所以讲 value 和 label 同时和传入语法进行比较
        return curLabel === curLanguage || curValue === curLanguage;
      });
    },
    // 更改模式
    onChangeMode(modeVal) {
      // 获取具体的语法类型对象
      let modeObj = this.getMode(modeVal);
      if (modeObj) {
        this.mode = modeObj.value;
        // 修改编辑器的语法配置
        this.editer.setOption("mode", `text/${this.mode}`);
        // 允许父容器通过以下函数监听当前的语法值
        this.$emit("modeChange", this.mode);
      }
    },
  },
  data() {
    return {
      // 协同编辑必要参数
      socket: "",
      shareConnection: "",
      shareDoc: "",
      docName: "",
      authorName: "",

      // 内部真实的内容
      code: "",
      // 默认的语法类型
      mode: "javascript",
      // 编辑器实例
      editer: null,
      // 默认配置
      editerOptions: {
        tabSize: 2,
        theme: "neat",
        lineNumbers: true,
        line: true,
        foldGutter: true,
        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
        autoCloseBrackets: true,
        // autoCloseTags: true,
        extraKeys: {
          Alt: "autocomplete",
        },
      },
      // 支持切换的语法高亮类型，对应 JS 已经提前引入
      // 使用的是 MIME-TYPE ，不过作为前缀的 text/ 在后面指定时写死了
      modes: [
        {
          value: "html",
          label: "XML/HTML",
        },
        {
          value: "css",
          label: "CSS",
        },
        {
          value: "javascript",
          label: "JavaScript",
        },
        {
          value: "markdown",
          label: "Markdown",
        },
        {
          value: "x-python",
          label: "Python",
        },
        {
          value: "x-vue",
          label: "Vue",
        },
      ],
    };
  },
};
</script>
<style>
.CodeMirror {
  height: 400px;
}
</style>
